package com.aliyun.heiyu.powermaster.server.service;

import com.aliyun.heiyu.common.util.*;
import com.aliyun.heiyu.powermaster.proto.*;
import com.aliyun.heiyu.powermaster.server.Error;
import com.aliyun.heiyu.powermaster.server.dao.BreaklineDao;
import com.aliyun.heiyu.powermaster.server.dao.DeviceServerDao;
import com.aliyun.heiyu.powermaster.server.dao.entity.*;
import com.aliyun.heiyu.powermaster.server.dao.enums.DeviceErrorEnum;
import com.aliyun.heiyu.powermaster.server.dao.impl.BreaklineImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.CapFminImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.DeviceServerDaoImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.StateGridCapTaskItemImpl;
import com.aliyun.heiyu.powermaster.server.factory.TransDeviceManager;
import com.aliyun.heiyu.powermaster.server.manager.*;
import com.aliyun.heiyu.powermaster.server.obj.po.VerifyEdgePO;
import com.aliyun.heiyu.powermaster.server.rotary.service.AirService;
import com.aliyun.heiyu.powermaster.server.rotary.service.impl.AirServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.net.URI;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


public class PowerDataServiceImpl implements PowerDataService {
    private static Logger logger = LoggerFactory.getLogger(PowerDataServiceImpl.class);

    private DeviceManager deviceManager;
    private ThunderManager thunderProvider;
    private StrategyManager strategyManager;
    private QosManager qosManager;
    private Set<String> ipmiSet;
    private Map<String,String> warningMap = getWarningMap();
    private Map<String,String> typeMap = getTypeMap();
    private AirService airService;
    private String aiIp;
    private DeviceServerDao deviceServerDao;
    private WarningService warningService;

    public PowerDataServiceImpl() {
        aiIp = PropertiesUtil.getValue("serverIp.properties", "aiIp");
        if(StringUtil.isEmpty(aiIp)){
            aiIp = "localhost";
        }
        this.warningService = new WarningServiceImpl();
        this.deviceServerDao = new DeviceServerDaoImpl();
        this.deviceManager = TransDeviceManager.getDeviceServiceTrans();
        this.thunderProvider = new ThunderManagerImpl();
        strategyManager = StrategyManager.getInstance();
        qosManager = QosManagerImpl.getInstance();
        this.airService = new AirServiceImpl();
    }

    /**
     * 新增设备
     * @param request
     * @return
     */
    public AddDeviceReply.Builder insert(AddDeviceRequest request) {
        AddDeviceReply.Builder builder = AddDeviceReply.newBuilder();
        Device2 device = request.getDevice();
        String deviceId = device.getDeviceId();
        if (deviceManager.checkDiviceExit(deviceId)) {
            String s = "新增失败，设备编号已经存在";
            return builder.setErrCode(DeviceErrorEnum.DEVICE_EXIT_ERROR.getCode()).setErrMsg(s);
        }
        HashMap<String, String> map = getInsertMap(device);
        String errMsg = checkInsertMap(map);    //字段校验-luo
        if (errMsg != null) {
            return builder.setErrCode(612).setErrMsg("新增失败，"+errMsg);
        }

        boolean bool = false;
        try {
            bool = deviceManager.insert(map);
        } catch (SQLException e) {
            bool = false;
        }

        if (bool) {
            return builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        } else {
            return builder.setErrCode(DeviceErrorEnum.INSERT_ERROR.getCode()).setErrMsg(DeviceErrorEnum.INSERT_ERROR.getMsg());
        }

    }

    /**
     * 更新设备
     * @param request
     * @return
     */
    public UpdateDeviceReply.Builder update(UpdateDeviceRequest request) {
        UpdateDeviceReply.Builder builder = UpdateDeviceReply.newBuilder();
        Device2 device = request.getDevice();
        String deviceId = device.getDeviceId();
        if (StringUtil.isEmpty(deviceId) || deviceManager.findOneDeviceCommon(deviceId) == null) {
            logger.error("修改失败，该设备不存在");
            return builder.setErrCode(DeviceErrorEnum.PARAM_ERROR.getCode()).setErrMsg("修改失败，该设备不存在");
        }

        HashMap<String, String> map = getUpdateMap(device);
        String errMsg = checkInsertMap(map);
        if (errMsg != null) {
            return builder.setErrCode(612).setErrMsg(errMsg);
        }

        boolean bool = false;
        try {
            bool = deviceManager.update(map);
        } catch (SQLException e) {
            bool = false;
        }

        if (bool) {
            return builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        } else {
            return builder.setErrCode(DeviceErrorEnum.UPDATE_ERROR.getCode()).setErrMsg(DeviceErrorEnum.UPDATE_ERROR.getMsg());
        }

    }

    /**
     * 删除设备
     * @param deviceId
     * @return
     */
    public DeleteDeviceReply.Builder delete(String deviceId) {
        DeleteDeviceReply.Builder builder = DeleteDeviceReply.newBuilder();
        if (!StringUtil.isEmpty(deviceId)) {
            String[] deviceIds = deviceId.split(",");
            //如果有机柜，检查机柜是否达到删除条件
            boolean b = deviceManager.checkDeleteParams(deviceIds);
            if (!b) {
                return builder.setErrCode(DeviceErrorEnum.DELETE_CABINET_ERROR.getCode()).setErrMsg(DeviceErrorEnum.DELETE_CABINET_ERROR.getMsg());
            }

            Boolean bool = null;
            try {
                bool = deviceManager.delete(deviceIds);
            } catch (SQLException e) {
                bool = false;
            }

            if (!bool) {
                return builder.setErrCode(DeviceErrorEnum.DELETE_ERROR.getCode()).setErrMsg(DeviceErrorEnum.DELETE_ERROR.getMsg());
            }
            return builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        } else {
            return builder.setErrCode(DeviceErrorEnum.PARAM_ERROR.getCode()).setErrMsg(DeviceErrorEnum.PARAM_ERROR.getMsg());
        }
    }

    /**
     * 导出设备列表
     * @param request
     * @return
     */
    public ExportDevicesReply exportDeviceList(ExportDevicesRequest request) {
        ExportDevicesReply.Builder builder = ExportDevicesReply.newBuilder();
        Device2List.Builder deviceListBuilder = Device2List.newBuilder();
        String condition = request.getCondition();
        String type = request.getType();
        String business = request.getBusinessType();
        String usageStatus = request.getUsageStatus();
        String cabinetSn = request.getCabinetSn();
        String locationId = request.getLocationId();
        Map<String, Map<String, String>> deviceDetailMap = deviceManager.getDeviceDetailByCondition(cabinetSn, condition, type, business, usageStatus,locationId);
        if (deviceDetailMap != null && !deviceDetailMap.isEmpty()) {
            Set<String> keys = deviceDetailMap.keySet();
            for (String key : keys) {
                Map<String, String> deviceMap = mapToDetailMap(deviceDetailMap.get(key));
                //todo 去掉一重转化
                Device2 device2 = mapToDevice2(deviceMap);
                deviceListBuilder.addDevice(device2);
            }
        }
        builder.setData(deviceListBuilder).setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        return builder.build();
    }

    /**
     * 导入：批量新增功能
     */
    public ImportDevicesReply importDeviceList(ImportDevicesRequest request) {
        ImportDevicesReply.Builder builder = ImportDevicesReply.newBuilder();
        List<Device2> device3List = request.getDevicesList();

        int size = device3List.size();
        if (size == 0) {
            return builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg()).build();
        }

        String errMsg = null;
        HashSet<String> deviceIdSet = new HashSet<>();
        HashSet<String> deviceIpSet = new HashSet<>();
        HashSet<String> locatedIdSet = new HashSet<>();
        List<DeviceCommonEntity> allServer = deviceManager.findAllDeviceCommon();
        Set<String> collect = new HashSet<>();
        if (allServer != null && allServer.size() != 0) {
            collect = allServer.stream().map(o -> o.getDevice_id()).collect(Collectors.toSet());
        }

        List<Map<String, String>> list = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            Device2 device2 = device3List.get(i);
            HashMap<String, String> deviceMap = getInsertMap(device2);
            String type1 = typeMap.get(deviceMap.get("type"));
            HashSet<String> typeSet = new HashSet<>(typeMap.values());
            if(StringUtil.isEmpty(type1) || !typeSet.contains(type1)){
                type1="";
            }
            String deviceId = device2.getDeviceId();
            if (collect.contains(deviceId)) {
                errMsg = "导入"+type1+"失败，"+"设备编号:" + deviceId + "已经存在";
                break;
            }
            if (deviceIdSet.contains(deviceId)) {
                errMsg = "导入"+type1+"失败，"+"设备编号:" + deviceId + "不允许有重复";
                break;
            } else {
                deviceIdSet.add(deviceId);
            }
            errMsg = checkInsertMap(deviceMap);
            if (errMsg != null) {
                errMsg = "导入"+type1+"失败，"+errMsg;
                break;
            }

            if(deviceMap.get("type").equals("server")){

                if(StringUtils.isNotBlank(device2.getServerType())){
                    if(!"arm".equals(device2.getServerType()) && !"x86".equals(device2.getServerType()) ){
                        errMsg = "导入服务器设备类型失败，"+"服务器设备类型只能是x86 或arm";
                    }
                }else{
                    errMsg = "导入服务器设备类型失败，"+"服务器设备类型不允许为空";
                    break;
                }

                if (deviceIpSet.contains(device2.getIp())) {
                    errMsg = "导入"+type1+"失败，"+"设备IP:" + device2.getIp() + "不允许有重复";
                    break;
                } else {
                    deviceIpSet.add(device2.getIp());
                }
            }
            if (locatedIdSet.contains(device2.getLocationId())) {
                errMsg = "导入"+type1+"失败，"+"设备位置号:" + device2.getLocationId() + "不允许有重复";
                break;
            } else {
                locatedIdSet.add(device2.getLocationId());
            }
            list.add(deviceMap);
        }

        if (errMsg == null || errMsg.isEmpty()) {
            try {
                deviceManager.insertAll(list);
            } catch (SQLException throwables) {
                builder.setErrCode(DeviceErrorEnum.INSERT_ERROR.getCode()).setErrMsg(DeviceErrorEnum.INSERT_ERROR.getMsg());
            }
            builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        } else {
            builder.setErrCode(DeviceErrorEnum.INSERT_ERROR.getCode()).setErrMsg(errMsg);
        }
        return builder.build();
    }

    /**
     * 根据条件获取设备列表
     *
     * @param request
     * @return
     */
    public GetDevicesReply getDeviceList(GetDevicesRequest request) {
        GetDevicesReply.Builder builder = GetDevicesReply.newBuilder();
        DeviceListData.Builder deviceListDataBuild = DeviceListData.newBuilder();
        String condition = request.getCondition();
        String type = request.getType();
        String business = request.getBusinessType();
        String usageStatus = request.getUsageStatus();
        if (!"1".equals(usageStatus) && !"2".equals(usageStatus) && !StringUtil.isEmpty(usageStatus)) {
            builder.setErrCode(DeviceErrorEnum.PARAM_ERROR.getCode()).setErrMsg("使用状态必须是正常或者故障");
            return builder.build();
        }
        String cabinetSn = request.getCabinetSn();
        String locationId = request.getLocationId();
        int pageSize = request.getPageSize();
        int pageNum = request.getPageNum();
        int totalCount = deviceManager.getTotalCount(cabinetSn, condition, type, business, usageStatus, locationId);
        if (totalCount == 0) {
            //没有满足条件的数据
            return builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg()).setData(deviceListDataBuild).build();
        }

        //获取静态设备列表
        List<DeviceCommonEntity> deviceCommonList = deviceManager.getDeviceCommonByCondition(cabinetSn, condition, type, business, usageStatus, pageNum, pageSize, totalCount, locationId);
        Map<String, PowerInfo> devicePowerMap = thunderProvider.getPowerInfo(deviceCommonList);
        List<String> list = new ArrayList<>(deviceCommonList.size());
        for (DeviceCommonEntity deviceCommonEntity : deviceCommonList) {
            String deviceId = deviceCommonEntity.getDevice_id();
            list.add(deviceId);
        }
        for (DeviceCommonEntity deviceCommonEntity : deviceCommonList) {
            String deviceId = deviceCommonEntity.getDevice_id();
            DeviceCommon.Builder deviceBuilder = DeviceCommon.newBuilder();
            //从Powermap中获取power 的int值
            PowerInfo powerInfo = devicePowerMap.get(deviceId);
            if (powerInfo != null) {
                int power = powerInfo.getServerPower();
                deviceBuilder.setPower(power);
                deviceBuilder.setBaudRate(getNotNull(powerInfo.getBaudRate()));
            }
            //获取对应设备的应用策略
            StrategyDetail strategy = strategyManager.getStrategyDetailByDeviceId(deviceId);
            if(null == strategy){
                strategy = StrategyDetail.newBuilder().build();
            }
            deviceBuilder.setDeviceId(deviceCommonEntity.getDevice_id()).setType(getNotNull(deviceCommonEntity.getType()))
                .setRoom(getNotNull(deviceCommonEntity.getRoom())).setRatedPower(StringUtil.convertDouble(deviceCommonEntity.getRated_power()))
                .setAdministrator(getNotNull(deviceCommonEntity.getAdministrator())).setCreateTime(getNotNull(deviceCommonEntity.getCreate_time()))
                .setUsageStatus(getNotNull(deviceCommonEntity.getUsage_status())).setBusinessType(getNotNull(deviceCommonEntity.getBusiness_type()))
                .setIp(getNotNull(deviceCommonEntity.getIp())).setModifiedTime(getNotNull(deviceCommonEntity.getModified_time()))
                .setLocatedCabinet(getNotNull(deviceCommonEntity.getLocated_cabinet())).setStrategy(strategy).setManufacturer(getNotNull(deviceCommonEntity.getManufacturer()));
            deviceListDataBuild.addDeviceList(deviceBuilder);
        }
        deviceListDataBuild.setTotal(totalCount).setCurrentPage(pageNum);
        builder.setData(deviceListDataBuild).setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        return builder.build();
    }

    /**
     * 获取设备静态信息详情
     * @param request
     * @return
     */
    public GetDeviceDetailReply getDeviceDetail(GetDeviceDetailRequest request) {
        GetDeviceDetailReply.Builder resultBuilder = GetDeviceDetailReply.newBuilder();
        ResultMap.Builder builder = ResultMap.newBuilder();
        String deviceSn = request.getDeviceSn();
        Map<String, String> device = deviceManager.findOneDeviceDetail(deviceSn);
        device = mapToDetailMap(device);
        if (device == null) {
            resultBuilder = resultBuilder.setErrCode(DeviceErrorEnum.PARAM_DEVICEID_ERROR.getCode()).setErrMsg(DeviceErrorEnum.PARAM_DEVICEID_ERROR.getMsg());
        } else {
            Iterator<Map.Entry<String, String>> iterator = device.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry) iterator.next();
                String key = entry.getKey();
                String value = entry.getValue();
                if (value == null) {
                    value = "";
                }
                if (key != null && !"class".equals(key)) {
                    builder.putMap(key, value);
                }
            }
            resultBuilder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage()).setData(builder.build());
        }
        return resultBuilder.build();
    }

    /**
     * 获取设备动态信息
     * @param request
     * @return
     */
    @Override
    public DeviceDynamicReply dynamicDetail(DynamicDeviceRequest request) {
        DeviceDynamicReply.Builder builder = DeviceDynamicReply.newBuilder();
        ResultMap.Builder result = ResultMap.newBuilder();
        Map<String, String> map = new HashMap<>();
        String deviceSn = request.getDeviceSn();
        //判断设备是否存在 静态数据
        Map<String, String> device = deviceManager.findOneDeviceDetail(deviceSn);
        if (device == null) {
            builder.setErrCode(DeviceErrorEnum.PARAM_DEVICEID_ERROR.getCode())
                .setErrMsg(DeviceErrorEnum.PARAM_DEVICEID_ERROR.getMsg());
            return builder.build();
        }
        String type = device.get("type");
        //获取动态数据
        Map<String, String> powerInfo = thunderProvider.getPowerInfoData(deviceSn, type);
        String serverType = deviceServerDao.selectServerType(deviceSn);
        if (powerInfo != null && !powerInfo.isEmpty()) {
            powerInfo.remove("server_power");
            map.putAll(powerInfo);
            String cpuFreq = map.get("cpu_freq");
            if(!StringUtil.isEmpty(cpuFreq)){
                if("arm".equals(serverType)){
                    map.put("qos","");
                }else{
                    map.put("qos", String.valueOf(qosManager.computingQOS(Integer.valueOf(cpuFreq))));
                }
            }
        }
        if ("server".equals(type)){
            CapFminEntity capFminEntity = qosManager.findOne(deviceSn);
            if (capFminEntity != null) {
                if("arm".equals(serverType)){
                    map.put("comment_freq","");
                    map.put("uncapping_freq","");
                }else{
                    map.put("comment_freq", String.valueOf(capFminEntity.getFmin()));
                    map.put("uncapping_freq", String.valueOf(capFminEntity.getF_uncapping()));
                }

            }
        }
        if ("server".equals(type) || "air".equals(type)) {
            //获取策略
            StrategyEntity strategy = strategyManager.getStrategyByDeviceId(deviceSn);
            if (strategy != null) {
                map.put("strategy_id", String.valueOf(strategy.getStrategyID()));
                map.put("strategy_name", String.valueOf(strategy.getStrategyName()));
            }
        }
        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry) iterator.next();
            String key = entry.getKey();
            String value = entry.getValue();
            if (value == null) {
                value = "";
            }
            if (key != null && !"class".equals(key)) {
                result.putMap(key, value);
            }
        }
        return builder.setErrCode(Error.SUCCESS.getCode())
            .setErrMsg(Error.SUCCESS.getMessage())
            .setData(result.build()).build();
    }

    /**
     * 根据条件获取设备ID集合
     * @param type
     * @return
     */
    @Override
    public GetDeviceSnsReply getDeviceSns(String type) {
        GetDeviceSnsReply.Builder builder = GetDeviceSnsReply.newBuilder();
        builder.setErrCode(Error.SUCCESS.getCode())
            .setErrMsg(Error.SUCCESS.getMessage());
        List<Map<String, String>> deviceSnList = deviceManager.findDeviceSnByType(type);
        GetDeviceSnsReply.Data.Builder dataBuilder = GetDeviceSnsReply.Data.newBuilder();
        if(deviceSnList != null){
            for (Map<String, String> map : deviceSnList){
                GetDeviceSnsReply.DeviceSnAndType.Builder builder1 = GetDeviceSnsReply.DeviceSnAndType.newBuilder();
                builder1.setDeviceId(getNotNull(map.get("device_id")));
                builder1.setType(getNotNull(map.get("type")));
                builder1.setIp(getNotNull(map.get("ip")));
                dataBuilder.addDevices(builder1.build());
            }
        }
        builder.setData(dataBuilder.build());
        return builder.build();
    }

    /**
     * 1.通过sn获取power集合
     * 2.通过sn获取capping_freq,uncapping_freq
     * 3.通过ip获取power的状态
     * 4.合并
     *
     * @param sn        设备ID
     * @param startTime 开始时间 默认为当前时间三天前的凌晨
     * @param endTime   结束时间
     * @param interval  时间间隔 默认为1分钟，单位分钟
     * @return
     */
    public GetCappingFreq1Reply.Builder getcapFreq(String sn, String startTime, String endTime, int interval) {
        GetCappingFreq1Reply.Builder resultBuilder = GetCappingFreq1Reply.newBuilder();
        CappingFreqs1.Builder builder = CappingFreqs1.newBuilder();
        if (StringUtil.isEmpty(sn)) {
            logger.error("参数不能为空");
            return resultBuilder.setErrCode(DeviceErrorEnum.PARAM_DEVICEID_ERROR.getCode()).setErrMsg(DeviceErrorEnum.PARAM_DEVICEID_ERROR.getMsg());
        }

        DeviceCommonEntity device = deviceManager.findOneDeviceCommon(sn);
        if (device == null || !"server".equals(device.getType())) {
            logger.warn("data is emptied");
            return resultBuilder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        }

        String ip = device.getIp();
        if (StringUtil.isEmpty(startTime)) {
            //默认为当前3天
            Date dNow = new Date();  //当前时间
            Calendar calendar = Calendar.getInstance(); //得到日历
            calendar.setTime(dNow);
            calendar.add(Calendar.DAY_OF_MONTH, -3); //设置为前3天
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            startTime = format.format(calendar.getTime()) + " 00:00:00";
        }
        if (StringUtil.isEmpty(endTime)) {
            //默认为当前天
            long end = System.currentTimeMillis();
            endTime = DateUtil.millisecondToDate(end);
        }
        interval = (interval == 0 ? 1 : interval);
        int milInter = interval * 60 * 1000;

        FreqList.Builder actuals = FreqList.newBuilder();
        FreqList.Builder recommends = FreqList.newBuilder();
        FreqList.Builder nocappings = FreqList.newBuilder();
        TimeList.Builder times = TimeList.newBuilder();
        CappingList.Builder cappings = CappingList.newBuilder();
        QosList.Builder qosList = QosList.newBuilder();

        startTime = formatStartTime(startTime, interval);
        ArrayList<PowerInfo> powerslist1 = getPowerInfoBylabel(sn, startTime, endTime, milInter);
        Map<Integer, CapFminEntity> capFmins = getCapFminMapForPosition(sn, startTime, endTime, milInter);
        Map<Integer, Map<String, String>> capTasks = getCapTaskMapForPosition(ip, startTime, endTime, milInter);
        boolean capStatus = false;
        for (int i = 0; i < powerslist1.size(); i++) {
            //添加freq和time
            PowerInfo info = powerslist1.get(i);
            long cpuFreq = info.getCpuFreq();
            String collectTime = info.getCollectTime();
            actuals.addFreq(cpuFreq);
            times.addTime(collectTime);
            //添加CappingFmin,通过点位获取判断
            CapFminEntity capFmin = capFmins.get(i);
            if (capFmin != null) {
                recommends.addFreq(capFmin.getFmin());
                nocappings.addFreq(capFmin.getF_uncapping());
            } else {
                recommends.addFreq(0);
                nocappings.addFreq(0);
            }
            ////添加Qos
            qosList.addQos(qosManager.computingQOS((int) cpuFreq));
            //添加capping状态,通过点位获取判断
            Map<String, String> capItemMap = capTasks.get(i);
            if (capItemMap != null) {
                String param1 = capItemMap.get("param");
                if (!"-1".equals(param1) && param1 != null) {
                    capStatus = true;
                } else {
                    capStatus = false;
                }
            }
            if (capStatus) {
                cappings.addFreq(String.valueOf(cpuFreq));//1表示capping，param为设定参数
            } else {
                cappings.addFreq("");
            }
        }

        builder.setActual(actuals).setNocapping(nocappings).setRecommend(recommends).setCapping(cappings).setTimes(times).setQosList(qosList).build();
        return resultBuilder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage()).setData(builder.build());
    }

    /**
     * 获取标签下的一段时间内的powerinfo集合
     *
     * @param label     标签，值为空默认返回标签列表中的所有标签
     * @param startTime 开始时间，值为空查询瞬时数据
     * @param endTime   结束时间，值为空默认当前时间
     * @param interval  间隔时间，默认30秒。单位分钟
     * @return
     */
    public GetPowerInfoReply getPower(String label, String startTime, String endTime, int interval) {
        GetPowerInfoReply.Builder replyBuild = GetPowerInfoReply.newBuilder();
        List<String> labels = getLabels(label);

        //1.starttime 为空 查询瞬时数据
        if (StringUtil.isEmpty(startTime)) {
            for (String s : labels) {
                PowerInfo powerInfo = getPowerInfoBylabel(s);
                if (powerInfo == null) {
                    continue;
                }
                PowerByLabel.Builder powerByLabelBuild = PowerByLabel.newBuilder().setLabel(s).addInfos(powerInfo);
                replyBuild.addData(powerByLabelBuild.build());
            }

            return replyBuild.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg()).build();
        }

        //2.starttime 不为空 查询时间段间隔数据
        if (StringUtil.isEmpty(endTime)) {
            endTime = DateUtil.millisecondToDate(System.currentTimeMillis());
        }
        int milInter = 0;
        if (interval <= 0) {
            milInter = 30 * 1000;  //默认30秒
        } else {
            milInter = interval * 60 * 1000;
        }
        startTime = formatStartTime(startTime, interval);
        for (String s : labels) {
            ArrayList<PowerInfo> powerInfos = getPowerInfoBylabel(s, startTime, endTime, milInter);
            PowerByLabel.Builder builder = PowerByLabel.newBuilder();
            for (PowerInfo info : powerInfos) {
                info = info.toBuilder().setServerPower(info.getSumSerPower()).build();
                builder.addInfos(info);
            }
            //判断label是否是服务器编号，获取破线数据
            DeviceCommonEntity oneDeviceCommon = deviceManager.findOneDeviceCommon(label);
            if (oneDeviceCommon != null) {
                ArrayList<BreakLine> pieces = getBreakData(s, startTime, endTime, milInter);
                for (BreakLine entity : pieces) {
                    builder.addPieces(entity);
                }
                if (interval == 0) {
                    String time = formatStartTime(endTime, 0);
                    List<AiInfo> list = getAIPowerInfos(label, time);
                    if (list != null) {
                        for (AiInfo aiInfo : list) {
                            builder.addAiInfos(aiInfo);
                        }
                    }
                }
            }
            builder.setLabel(s);
            replyBuild.addData(builder.build());
        }

        return replyBuild.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg()).build();
    }

    private JSONArray getModelInferenceInfo(String taskId, String deviceId){
        try {
            URI uri = new URIBuilder().setScheme("https")
                .setHost(aiIp)
                .setPath("/v2/models/inference")
                .setParameter("task_id", taskId)
                .setParameter("data",deviceId)
                .setParameter("token","market_token")
                .build();
            JSONObject jsonObject = HttpUtil.getRequest(uri);
            logger.debug("url == {}" , LogUtils.vaildlog(uri.toString()));
            if (jsonObject == null || jsonObject.getInt("err_code") != 0) {
                logger.error("访问服务器失败,");//请求失败
                return null;
            }
            JSONArray jsonArray = jsonObject.getJSONArray("data");
            return jsonArray;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    public List<AiInfo> getAIPowerInfos(String sn, String time) {
        ArrayList<AiInfo> list = new ArrayList<>();
        JSONArray aiCpuInfos = getModelInferenceInfo("cpu_pred",sn);
        JSONArray aiPowerInfos = getModelInferenceInfo("power_pred",sn);
        if(aiCpuInfos == null || aiPowerInfos == null){
            return list;
        }
        long startPointTime = DateUtil.dateToMillisecond(time);
        int size = aiCpuInfos.length();
        for(int i = 0; i < size; i++){
            Double cpu = aiCpuInfos.getDouble(i);
            Double power = aiPowerInfos.getDouble(i);
            //判断预测功耗是否大于功耗上限
            warmPower(sn,power);
            logger.info("前端调用的服务器预测功率上限设备编号【{}】，服务器上限温度【{}】",LogUtils.vaildlog(sn),power);
            long pointTime = startPointTime + 30 * 1000 * i;
            AiInfo build = AiInfo.newBuilder()
                .setServerPower(String.valueOf(power))
                .setCpuUsage(String.valueOf(cpu))
                .setCollectTime(DateUtil.millisecondToDate(pointTime))
                .build();
            list.add(build);
        }
        return list;
    }

    /**
     * 获取数据大盘需要的统计数据
     *
     * @return
     */
    public GetStatisticsReply getStatistics() {
        GetStatisticsReply.Builder newBuilder = GetStatisticsReply.newBuilder();
        newBuilder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        Statistics.Builder builder = Statistics.newBuilder();
        int sumPowerCbinet = 0;
        int sumRatedCabinet = 0;
        int numServer = 0;
        int sumPowerServer = 0;
        int sumRatedServer = 0;
        int numAir = 0;
        int numPdu = 0;
        int sumPowerAir = 0;
        int sumPowerPdu = 0;
        int sumRatedAir = 0;
        int sumRatedPdu = 0;

        List<DeviceCommonEntity> devices = deviceManager.findAllDeviceCommon();
        ArrayList<String> snList = new ArrayList<>();
        for (DeviceCommonEntity deviceCommon : devices) {
            String type = deviceCommon.getType();
            String sn = deviceCommon.getDevice_id();
            int ratedPower = (int) StringUtil.convertDouble(deviceCommon.getRated_power());
            if ("server".equals(type)) {
                snList.add(deviceCommon.getDevice_id());
                numServer += 1;
                sumRatedServer += ratedPower;
            } else if ("cabinet".equals(type)) {
                sumRatedCabinet += ratedPower;
            } else if ("air".equals(type)) {
                PowerInfo info = thunderProvider.getPowerInfo(sn, type);
                if (info != null) {
                    sumPowerAir += info.getServerPower();
                }
                numAir += 1;
                sumRatedAir += ratedPower;
            } else if ("pdu".equals(type)) {
                PowerInfo info = thunderProvider.getPowerInfo(sn, type);
                if (info != null) {
                    sumPowerPdu += info.getServerPower();
                }
                numPdu += 1;
                sumRatedPdu += ratedPower;
            }
        }
        String[] snArray = snList.toArray(new String[snList.size()]);

        Map<String, PowerInfo> serverPowerInfo = thunderProvider.getServerPowerInfo(snArray);
        List<PowerInfo> powerInfos = new ArrayList<PowerInfo>(serverPowerInfo.values());
        //powerInfos为null，有异常
        if (powerInfos != null && !powerInfos.isEmpty()) {
            PowerInfo.Builder powerInfo = getSumPowerInfo(powerInfos, 1);
            sumPowerServer = powerInfo.getSumSerPower();
            double cpuUsage = powerInfo.getCpuUsage();
            builder.setCpuUsage(cpuUsage);
            builder.setServerPower(sumPowerServer);
        }
        sumPowerCbinet = sumPowerServer;
        builder.setOtherPower(sumPowerAir + sumPowerPdu);
        builder.setServerNum(numServer);
        builder.setOtherNum(numAir + numPdu);
        builder.setServerUsage(getMerchant(sumPowerServer, sumRatedServer));
        builder.setCabinetUsage(getMerchant(sumPowerCbinet, sumRatedCabinet));
        int powerAll = sumPowerServer + sumPowerAir + sumPowerPdu;
        int ratedPowerAll = sumRatedServer + sumRatedAir + sumRatedPdu;
        builder.setDeviceUsage(getMerchant(powerAll, ratedPowerAll));

        newBuilder.setData(builder);

        return newBuilder.build();
    }

    @Override
    public UpdateDeviceDynamicReply.Builder updateDynamic(UpdateDeviceDynamicRequest request) {
        UpdateDeviceDynamicReply.Builder builder = UpdateDeviceDynamicReply.newBuilder();
        String deviceId = request.getDeviceId();

        if (StringUtil.isEmpty(deviceId) || deviceManager.findOneDeviceCommon(deviceId) == null) {
            logger.error("device don't existed");
            return builder.setErrCode(DeviceErrorEnum.PARAM_ERROR.getCode()).setErrMsg(DeviceErrorEnum.PARAM_ERROR.getMsg());
        }
        Map<String, String> map = new HashMap<>();
        map.put("air_id", deviceId);
        map.put("evaporating_fan_speed", request.getEvaporatingFanRpm());
        map.put("cooling_setpoint", request.getRefrigeratingSetpoint());
        map.put("cooling_sensitivity", request.getRefrigeratingSensitivity());
        boolean bool = airService.setAirValue(map);
        if (bool) {
            return builder.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg());
        } else {
            return builder.setErrCode(DeviceErrorEnum.UPDATE_ERROR.getCode()).setErrMsg(DeviceErrorEnum.UPDATE_ERROR.getMsg());
        }
    }

    public GetPowerInfoReply getPowerForAi(String label, String startTime, String endTime, int interval) {

        GetPowerInfoReply.Builder replyBuild = GetPowerInfoReply.newBuilder();
        List<String> labels = getLabels(label);
        //starttime 不为空 查询时间段间隔数据
        if (StringUtil.isEmpty(endTime)) {
            endTime = DateUtil.millisecondToDate(System.currentTimeMillis());
        }
        int milInter = 30 * 1000;
        startTime = formatStartTime(startTime, interval);
        for (String s : labels) {
            ArrayList<PowerInfo> powerInfos = getPowerInfoBylabelForAi(s, startTime, endTime, milInter);
            PowerByLabel.Builder builder = PowerByLabel.newBuilder();
            for (PowerInfo info : powerInfos) {
                info = info.toBuilder().setServerPower(info.getSumSerPower()).build();
                builder.addInfos(info);
            }
            builder.setLabel(s);
            replyBuild.addData(builder.build());
        }
        return replyBuild.setErrCode(DeviceErrorEnum.SUCCESS.getCode()).setErrMsg(DeviceErrorEnum.SUCCESS.getMsg()).build();
    }


    /**
     * 获取label的当前功率PowerInfo
     * powerInfo.cpuusage 标签下设备的平均值
     * powerInfo.freq 标签下设备的平均值
     * powerInfo.server_poser 标签下设备的功率和
     *
     * @param label
     * @return
     */
    private PowerInfo getPowerInfoBylabel(String label) {
        //查询服务器列表
        List<DeviceCommonEntity> devices = deviceManager.findByType("server");
        if (devices == null || devices.size() == 0) {
            return null;
        }
        Map<String, PowerInfo> PowerInfos = thunderProvider.getPowerInfo(devices);
        if (PowerInfos == null || PowerInfos.size() < 1) {
            return null;
        }
        List<PowerInfo> powerInfos = new ArrayList<PowerInfo>(PowerInfos.values());
        PowerInfo.Builder powerInfo = getSumPowerInfo(powerInfos, 1);
        powerInfo.setServerPower(powerInfo.getSumSerPower());
        powerInfo.setEquipmentNumber(label);
        return powerInfo.build();
    }

    private ArrayList<PowerInfo> getPowerInfoBylabelForAi(String label, String startTime, String endTime, int milInter) {
        ArrayList<PowerInfo> powerslist = new ArrayList<>();
        long start = DateUtil.dateToMillisecond(startTime);
        int num = getPointNum(startTime, endTime, milInter);
        ArrayList<PowerInfo> allpowerInfos = new ArrayList<>();
        String[] deviceIdArray = deviceManager.findDeviceIdArrayByLabel(label);
        List<PowerInfo> powerInfos = thunderProvider.getServerPowerInfoByTime(deviceIdArray, startTime, endTime);
        if (powerInfos != null && powerInfos.size() > 0) {
            allpowerInfos.addAll(powerInfos);
        }
        powerslist = getPowerslist1(label, allpowerInfos, start, milInter, num);
        return powerslist;
    }

    /**
     * 将一段时间内的powerInfo集合进行时间间隔分组
     *
     * @param infos
     * @param start
     * @param milInter 间隔时间/毫秒
     * @param num      点位个数
     * @return
     */
    private ArrayList<PowerInfo> getPowerslist1(String label, List<PowerInfo> infos, long start, int milInter, int num) {
        ArrayList<ArrayList<PowerInfo>> powerList = new ArrayList<>();
        int size = milInter / 1000 / 60 <= 0 ? 1 : (int) (milInter / 1000 / 60 * 2);
        for (int j = 0; j < num; j++) {
            ArrayList<PowerInfo> list = new ArrayList<>();
            powerList.add(list);
        }
        ArrayList<PowerInfo> poList = new ArrayList<>();
        for (int f = 0; f < infos.size(); f++) {   //遍历一台设备的多个时间点的数据
            //获取info数组中的值对象
            PowerInfo info = infos.get(f);
            long cltime = DateUtil.dateToMillisecond(info.getCollectTime());
            int n = Integer.valueOf(String.valueOf((cltime - start) / milInter));
            if (n < num) { //保证不越界
                powerList.get(n).add(info);
            }
        }
        for (int i = 0; i < powerList.size(); i++) {
            ArrayList<PowerInfo> powerInfos = powerList.get(i);
            PowerInfo.Builder powerBuild = getSumPowerInfo(powerInfos, size);
            if (powerBuild == null) {
                powerBuild = PowerInfo.newBuilder();
            }
            String time = DateUtil.millisecondToDate(start + i * milInter);
            powerBuild.setEquipmentNumber(label);
            powerBuild.setCollectTime(time);
            poList.add(powerBuild.build());
        }
        return poList;
    }

    private int getPointNum(String startTime, String endTime, int milInter) {
        long start = DateUtil.dateToMillisecond(startTime);
        long end = DateUtil.dateToMillisecond(endTime);
        int num = (int) (end - start) / milInter;
        num = (end - start) % milInter < 30 * 1000 ? num : num + 1;
        num = (num == 0 ? 1 : num);
        return num;
    }

    /**
     * 获取label的一段时间内的功率PowerInfo集合
     *
     * @param label     标签
     * @param startTime NOTNULL
     * @param endTime   NOTNULL
     * @param milInter  间隔时间 单位秒
     * @return NOTNULL
     */
    private ArrayList<PowerInfo> getPowerInfoBylabel(String label, String startTime, String endTime, int milInter) {
        ArrayList<PowerInfo> powerslist = new ArrayList<>();
        long start = DateUtil.dateToMillisecond(startTime);
        long end = DateUtil.dateToMillisecond(endTime);
        int num = getPointNum(startTime, endTime, milInter);

        List<DeviceCommonEntity> devices = deviceManager.findByLabel(label);
        ArrayList<String> serverSnList = new ArrayList<>();
        ArrayList<PowerInfo> allpowerInfos = new ArrayList<>();
        for (DeviceCommonEntity device : devices) {
            if ("server".equals(device.getType())) {
                serverSnList.add(device.getDevice_id());
            } else if ("cabinet".equals(device.getType())) {
                String[] array1 = deviceManager.findDeviceIdArrayByLabel(device.getDevice_id());
                List<PowerInfo> infos = thunderProvider.getServerPowerInfoByTime(array1, startTime, endTime);
                allpowerInfos.addAll(infos);
            }
        }
        String[] deviceIdArray = deviceManager.findDeviceIdArrayByLabel(label);
        List<PowerInfo> powerInfos = thunderProvider.getServerPowerInfoByTime(deviceIdArray, startTime, endTime);
        if (powerInfos != null && powerInfos.size() > 0) {
            allpowerInfos.addAll(powerInfos);
        }
        powerslist = getPowerslist1(allpowerInfos, start, milInter, num);
        return powerslist;
    }


    /**
     * 将开始时间按照间隔时间格式化，向后初始化
     *
     * @param startTime NOTNULL
     * @param interval
     */
    private String formatStartTime(String startTime, int interval) {
        Date dNow = new Date(DateUtil.dateToMillisecond(startTime));
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.setTime(dNow);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        if (interval <= 0) {
            //将时间的秒格式化00或者30
            if (second >= 30) {
                calendar.set(Calendar.SECOND, 30);
            } else {
                calendar.set(Calendar.SECOND, 0);
            }
        } else {
            //将时间的分格式化
            if (minute % interval != 0) {
                int i = minute / interval;
                calendar.set(Calendar.MINUTE, i * interval);
            }
            calendar.set(Calendar.SECOND, 0);
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        startTime = format.format(calendar.getTime());
        return startTime;
    }

    /**
     * 将一段时间内的powerInfo集合进行时间间隔分组
     *
     * @param infos
     * @param start
     * @param milInter 间隔时间/毫秒
     * @param num      点位个数
     * @return
     */
    private ArrayList<PowerInfo> getPowerslist1(List<PowerInfo> infos, long start, int milInter, int num) {
        ArrayList<ArrayList<PowerInfo>> powerList = new ArrayList<>();
        int size = milInter / 1000 / 60 <= 0 ? 1 : (int) (milInter / 1000 / 60 * 2);
        for (int j = 0; j < num; j++) {
            ArrayList<PowerInfo> list = new ArrayList<>();
            powerList.add(list);
        }
        ArrayList<PowerInfo> poList = new ArrayList<>();
        for (int f = 0; f < infos.size(); f++) {   //遍历一台设备的多个时间点的数据
            //获取info数组中的值对象
            PowerInfo info = infos.get(f);
            long cltime = DateUtil.dateToMillisecond(info.getCollectTime());
            int n = Integer.valueOf(String.valueOf((cltime - start) / milInter));
            if (n < num) { //保证不越界
                powerList.get(n).add(info);
            }
        }
        for (int i = 0; i < powerList.size(); i++) {
            ArrayList<PowerInfo> powerInfos = powerList.get(i);
            PowerInfo.Builder powerBuild = getSumPowerInfo(powerInfos, size);
            if (powerBuild == null) {
                powerBuild = PowerInfo.newBuilder();
            }
            String time = DateUtil.millisecondToDate(start + i * milInter);
            powerBuild.setCollectTime(time);
            poList.add(powerBuild.build());
        }
        return poList;
    }


    //将list<Power>计算为一个PowerInfo
    private PowerInfo.Builder getSumPowerInfo(List<PowerInfo> infoList, int num) {
        if (infoList == null || infoList.size() < 1) {
            return null;
        }
        PowerInfo.Builder builder = PowerInfo.newBuilder();
        int sumSerPower = 0;
        int sumFramPower = 0;
        int sumCpuFreq = 0;
        double sumCpuUsage = 0;
        int number = infoList.size();
        String collectTime = infoList.get(0).getCollectTime();
        for (PowerInfo info : infoList) {
            long cpuFreq = info.getCpuFreq();
            int serverPower = info.getServerPower();
            double cpuUsage = info.getCpuUsage();
            int framPower = info.getFramePower();
            sumSerPower += serverPower;
            sumFramPower += framPower;
            sumCpuFreq += (int) cpuFreq;
            sumCpuUsage += cpuUsage;
        }
        int cpuFreq = (int) getAvg(sumCpuFreq, number);
        double cpuUsage = getAvg(sumCpuUsage, number);
        builder.setCpuUsage(cpuUsage).setServerPower((int) getAvg(sumSerPower, number)).setSumSerPower(sumSerPower / num)
            .setFramePower(sumFramPower).setCpuFreq(cpuFreq).setCollectTime(collectTime);
        return builder;
    }


    /**
     * 获取一段时间内的CanppingFmin与时间对应的点位
     *
     * @param sn        设备编号ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param milInter  时间间隔
     * @return NOTNULL
     */
    private Map<Integer, CapFminEntity> getCapFminMapForPosition(String sn, String startTime, String endTime, int milInter) {
        //todo 添加设备编号
        List<CapFminEntity> cappingFminList = getCappingFminList(sn, startTime, endTime);
        HashMap<Integer, CapFminEntity> resultMap = new HashMap<>();
        if (cappingFminList == null || cappingFminList.isEmpty()) {
            return resultMap;
        }
        int index = 0;
        ArrayList<CapFminEntity> capFminList = new ArrayList<>();
        for (int f = 0; f < capFminList.size(); f++) {
            CapFminEntity capFmin = capFminList.get(f);
            SimpleDateFormat formatNew = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = formatNew.format(capFmin.getDate());
            long start = DateUtil.dateToMillisecond(startTime);
            long cltime = DateUtil.dateToMillisecond(date);
            int n = Integer.valueOf(String.valueOf((cltime - start) / milInter));
            if (n == index) {
                capFminList.add(capFmin);
            } else {
                resultMap.put(index, getSumCapFmin(capFminList));
                index = n;
                capFminList.clear();
                capFminList.add(capFmin);
            }
            if (f == capFminList.size() - 1) {
                resultMap.put(index, getSumCapFmin(capFminList));
            }
        }
        return resultMap;
    }

    private CapFminEntity getSumCapFmin(ArrayList<CapFminEntity> capFminList) {
        if (capFminList == null || capFminList.size() < 1) {
            return null;
        }
        CapFminEntity stategridEntity = capFminList.get(0);
        int sumFmin = 0;
        int sumUncapping = 0;
        int number = capFminList.size();
        for (CapFminEntity capEntity : capFminList) {
            int fmin1 = capEntity.getFmin();
            int uncapping1 = capEntity.getF_uncapping();
            sumFmin += fmin1;
            sumUncapping += uncapping1;
        }
        stategridEntity.setFmin((int) getAvg(sumFmin, number));
        stategridEntity.setF_uncapping((int) getAvg(sumUncapping, number));
        return stategridEntity;
    }


    //获取一段时间内的CapTask与时间对应的点位 @return NOTNULL
    private Map<Integer, Map<String, String>> getCapTaskMapForPosition(String ip, String startTime, String endTime, int milInter) {
        ArrayList<Map<String, String>> capList = getCapTaskList(ip, startTime, endTime);
        HashMap<Integer, Map<String, String>> resultMap = new HashMap<>();
        int index = 0;
        ArrayList<Map<String, String>> mapList = new ArrayList<>();
        for (int i = 0; i < capList.size(); i++) {
            Map<String, String> capMap = capList.get(i);
            String capTime = capMap.get("gmt_create");
            long start = DateUtil.dateToMillisecond(startTime);
            long cltime = DateUtil.dateToMillisecond(capTime);
            int n = Integer.valueOf(String.valueOf((cltime - start) / milInter));
            if (n == index) {
                mapList.add(capMap);
            } else {
                resultMap.put(index, getSumCapMap(mapList));
                index = n;
                mapList.clear();
                mapList.add(capMap);
            }
            if (i == capList.size() - 1) {
                resultMap.put(index, getSumCapMap(mapList));
            }
        }
        return resultMap;
    }

    private Map<String, String> getSumCapMap(ArrayList<Map<String, String>> mapList) {
        //取最后一个作为最终点
        if (mapList != null && mapList.size() > 0) {
            return mapList.get(mapList.size() - 1);
        }
        return null;
    }

    /**
     * 获取设备一段时间内的capTask集合
     *
     * @param ip        设备IP
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return NOTNULL
     */
    private ArrayList<Map<String, String>> getCapTaskList(String ip, String startTime, String endTime) {
        ArrayList<Map<String, String>> capList = new ArrayList<>();
        StateGridCapTaskItemImpl capItemDao = new StateGridCapTaskItemImpl();
        List<Map<String, String>> capItems = capItemDao.findByCondition(ip, startTime, endTime);
        Map<String, String> capItem = capItemDao.findOneByCondition(ip, startTime);
        if (capItem != null) {
            capList.add(capItem);
        }
        if (capItems != null && capItems.size() > 0) {
            capList.addAll(capItems);
        }
        return capList;
    }

    //获取一段时间内CappingFmin集合
    private List<CapFminEntity> getCappingFminList(String deviceId, String startTime, String endTime) {
        //todo 没有设备编号参数
        Calendar calendarStart = Calendar.getInstance();
        calendarStart.setTime(new Date(DateUtil.dateToMillisecond(startTime)));
        //当开始时间不为整数点的时候，处理
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh");
        String startDb = format.format(calendarStart.getTime()) + ":00:00";
        //获取fmin和uncapping 从数据库连接
        CapFminImpl statedao = new CapFminImpl();
        List<CapFminEntity> all = statedao.findByTime(deviceId, startDb, endTime);
        return all;
    }

    /**
     * 得到百分比记过
     *
     * @param dividend 分子
     * @param divisor  分母
     * @return
     */
    private double getMerchant(int dividend, int divisor) {
        if (divisor == 0) {
            return 0;
        }
        return MathUtil.div(dividend * 100, divisor, 3);
    }

    //@return NOTNULL
    private List<String> getLabels(String label) {
        ArrayList<String> strings = new ArrayList<>();
        if (StringUtil.isEmpty(label)) {
            Set<Object> objects = PropertiesUtil.getProperties("labelStore.properties").keySet();
            for (Object o : objects) {
                strings.add(String.valueOf(o));
            }
        } else {
            strings.add(label);
        }
        return strings;
    }

    //获取破线数据
    private ArrayList<BreakLine> getBreakData(String sn, String startTime, String endTime, long milInter) {
        BreaklineDao dao = new BreaklineImpl();
        List<BreaklineEntity> lists = dao.findByTime(sn, startTime, endTime);
        ArrayList<BreakLine> pieces = new ArrayList<>();
        for (BreaklineEntity entity : lists) {
            //以开始时间为条件从数据库读取破线数据 防止结束时间小于破线间隔时间的情况
            long start = DateUtil.dateToMillisecond(startTime);
            long end = DateUtil.dateToMillisecond(endTime);
            long timeStart = DateUtil.dateToMillisecond(entity.getTime_start());
            long timeEnd = DateUtil.dateToMillisecond(entity.getTime_end());
            if (timeStart < end) {
                int numStart = 0;
                int numEnd = 0;
                if (timeStart > start) {
                    numStart = Integer.valueOf(String.valueOf((timeStart - start) / milInter));
                } else {
                    numStart = Integer.valueOf(String.valueOf((start - start) / milInter));
                }
                if (timeEnd < end) {
                    numEnd = Integer.valueOf(String.valueOf((timeEnd - start) / milInter));
                } else {
                    numEnd = Integer.valueOf(String.valueOf((end - start) / milInter));
                }
                BreakLine.Builder builder = BreakLine.newBuilder();
                BreakLine piece = builder.setGte(numStart).setLte(numEnd).setColor("red").setType(entity.getBreakline_type()).setComment(entity.getBreakline_comment()).build();
                pieces.add(piece);
            }
        }
        return pieces;
    }


    private double getAvg(double sum, int number) {
        if (number == 0) {
            return 0;
        }
        return MathUtil.div(sum, number, 3);
    }

    private String getNotNull(String s) {
        if (s == null) {
            s = "";
        }
        return s;
    }

    private String checkInsertMap(HashMap<String, String> map) {
        return checkInsertMap1(map);
    }

    private String checkInsertMap1(HashMap<String, String> map) {
        String type = map.get("type");
        StringBuffer buffer = new StringBuffer();
        String errMsg = map.get("ErrMsg");
        if (errMsg != null) {
            return errMsg;
        }

        int maxvo = 1000000;
        int minvo = 0;
        int maxcu = 1000000;
        int mincu = 0;
        double airSetTemperatureUpperLimit = 0,airSetTemperatureLowerLimit = 0;

        //double
        HashSet<String> set = new HashSet<>();
        set.add("rated_power");
        set.add("rent_price");
        set.add("width");
        set.add("weight");
        set.add("rated_voltage");
        set.add("refrigerating_capacity");
        set.add("heating_capacity");
        set.add("safety_valve_pressure");
        set.add("overheating_temperature");
        set.add("humidification_capacity");
        set.add("humidifier_rated_power");
        set.add("compressor_rated_power");
        set.add("heater_rated_power");
        set.add("fan_rated_power");
        set.add("turn_off_pressure");

        //int
        HashSet<String> set2 = new HashSet<>();
        set2.add("height");
        set2.add("power_supply_path");
        set2.add("maximum_voltage_limit");
        set2.add("minimum_voltage_limit");
        set2.add("maximum_current_limit");
        set2.add("minimum_current_limit");

        HashSet<String> set1 = new HashSet<>();
        set1.add("device_id");

        HashSet<String> set3 = new HashSet<>();
        set3.add("oob_ip");

        HashSet<String> set4 = new HashSet<>();
        set4.add("save_function");
        set4.add("incompatible_feature");

        HashSet<String> set5 = new HashSet<>();
        set5.add("device_id");
        set5.add("room");
        set5.add("administrator");
        set5.add("manufacturer");
        set5.add("business_type");
        set5.add("location_id");
        set5.add("device_model");
        set5.add("host_name");

        String validate = null;

        Set<Map.Entry<String, String>> entries = map.entrySet();

        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            //工控机校验
            if(ipcMap().containsKey(key)){
                boolean integer = MathUtil.isPositiveInteger(value);
                if(!integer){
                    return buffer.append(ipcMap().get(key)).append("应是不大于99999的正整数").toString();
                }
                int parseInt = Integer.parseInt(value);
                if(parseInt>99999){
                    return buffer.append(ipcMap().get(key)).append("应是不大于99999的正整数").toString();
                }
            }

            if("server_type".equals(key)){
                if(!value.equals("x86") && !value.equals("arm")){
                    return buffer.append(key).append("设置的值不在范围内").toString();
                }
            }

            if ("remarks".equals(key)) {
                validate = validate(key, value, 0, 500);
                if(!StringUtil.isEmpty(validate)){
                    return validate;
                }
                continue;
            }
            if ("modified_time".equals(key)) {
                continue;
            }
            if ("create_time".equals(key)) {
                continue;
            }
            //工控机没有生产商
            if(StringUtils.isNotBlank(type) && type.equals("ipc")&&key.equals("manufacturer")){
                continue;
            }
            //工控机没有生产年份
            if(StringUtils.isNotBlank(type) && type.equals("ipc")&&key.equals("manufacture_date")){
                continue;
            }

            if (StringUtil.isEmpty(value) ) {
                return warningMap.get(key) + "不能为空";
            }
            if (set1.contains(key)) {
                validate = validate(key, value, 15);
            } else {
                validate = validate(key, value, 100);
            }
            if (validate != null) {
                return validate;
            }
            //校验特殊字符
            if (set5.contains(key) && StringUtil.isContainSpecialChar(value)) {
                buffer.append(warningMap.get(key)+":" + key + "不合法");
                return buffer.toString();
            }
            if ("planned_server_number".equals(key)) {
                boolean b =StringUtil.isPositiveNum(value);
                if(b){
                    Integer i = Integer.valueOf(value);
                    b = i >= 0 && i <= 20;
                    if(b){
                        continue;
                    }
                }
                buffer.append(warningMap.get(key)+":" + key + "格式错误, 必须是0-20之间");
                return buffer.toString();
            }
            if ("located_cabinet".equals(key)) {
                Map<String, String> oneDeviceDetail = deviceManager.findOneDeviceDetail(value);
                if (oneDeviceDetail == null) {
                    return "所在机柜:"+value+"不存在";
                }
                DeviceCommonEntity info = deviceManager.findOneDeviceCommon(map.get("device_id"));
                if(info != null && value.equals(info.getLocated_cabinet())){
                    continue;
                }
                String plannedServerNumber = oneDeviceDetail.get("planned_server_number");
                int countOfCabinet = deviceManager.getCountOfCabinet(value);
                if (StringUtil.convertInt(plannedServerNumber) <= countOfCabinet) {
                    return "所在机柜:"+value+"服务器数量超过上限，不能正常使用";
                }
                continue;
            }
            if ("usage_status".equals(key)) {
                if (!value.equals("1") && !value.equals("2")) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                }
                continue;
            }
            if ("current_type".equals(key)) {
                if (!value.equals("1") && !value.equals("2") && !value.equals("3")) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                }
                continue;
            }
            if ("ipv6".equals(key)) {
                if (!StringUtil.isIpv6(value)) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                }
                continue;
            }
            if ("ip".equals(key)) {
                DeviceCommonEntity info = deviceManager.findOneDeviceCommon(map.get("device_id"));
                if (!StringUtil.isIp(value)) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                } else {
                    if (deviceManager.checkDiviceIpExit(value)) {
                        //info == null -- 新增   or  修改
                        if (null == info || !value.equals(info.getIp())) {
                            buffer.append(warningMap.get(key)+":" + key + "已经存在");
                            return buffer.toString();
                        }
                    }
                }
                continue;
            }
            if ("location_id".equals(key)){
                DeviceCommonEntity info = deviceManager.findOneDeviceCommon(map.get("device_id"));
                if (deviceManager.checkLocatedIdExit(value)) {
                    if(info == null || !info.getLocation_id().equals(value)){
                        buffer.append(warningMap.get(key)+":" + key + "已经存在");
                        return buffer.toString();
                    }
                }
                continue;
            }
            if ("manufacture_date".equals(key)) {
                if (!StringUtil.validDateEffecitive(value)) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                }
                continue;
            }
            if ("drive_release_time".equals(key)) {
                if (!StringUtil.validDateEffecitive(value)) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                }
                continue;
            }
            if (set.contains(key)) {
                if(StringUtil.isPositiveDouble(value)){
                    Double aDouble = Double.valueOf(value);
                    if(aDouble >= 0 && aDouble < 100000){
                        continue;
                    }
                }
                buffer.append(warningMap.get(key)+":" + key + "格式错误,必须是0-99999.999之间");
                return buffer.toString();
            } else if (set2.contains(key)) {
                if(StringUtil.isPositiveNum(value)){
                    Integer i = Integer.valueOf(value);
                    if(i >= 0 && i < 100000){
                        if ("maximum_voltage_limit".equals(key)) {
                            maxvo = i;
                        } else if ("minimum_voltage_limit".equals(key)) {
                            minvo = i;
                        } else if ("maximum_current_limit".equals(key)) {
                            maxcu = i;
                        } else if ("minimum_current_limit".equals(key)) {
                            mincu = i;
                        }
                        continue;
                    }
                }
                buffer.append(warningMap.get(key)+":" + key + "格式错误,必须是0-99999之间");
                return buffer.toString();
            } else if (set3.contains(key)) {
                boolean b = StringUtil.isIp(value);
                if (!b) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误,必须是合法的IP");
                    return buffer.toString();
                }
            } else if (set4.contains(key)) {
                if (!value.equals("on") && !value.equals("off")) {
                    buffer.append(warningMap.get(key)+":" + key + "格式错误");
                    return buffer.toString();
                }
            }

            //校验空调设置温度上限/下限；服务器：预测功耗上限
            if ("air_set_temperature_upper_limit".equals(key)){
                if (StringUtil.isEmpty(value)){
                    buffer.append(warningMap.get(key)+" 不能为空");
                    return buffer.toString();
                }
                if (!StringUtil.validDoubleInterval(Double.valueOf(value),0D,99999.999D)){
                    buffer.append(warningMap.get(key)+"air_set_temperature_lower_limit");
                    return buffer.toString();
                }
                airSetTemperatureUpperLimit = Double.parseDouble(value);

            }
            if ("air_set_temperature_lower_limit".equals(key)){
                if (StringUtil.isEmpty(value)){
                    buffer.append(warningMap.get(key)+" 不能为空");
                    return buffer.toString();
                }
                if (!StringUtil.validDoubleInterval(Double.parseDouble(value),0D,99999.999D)){
                    buffer.append(warningMap.get(key)+"（0~100000(不含100000)，且最多保留三位小数）");
                    return buffer.toString();
                }
                airSetTemperatureLowerLimit = Double.parseDouble(value);

            }
            if ("forecast_power_upper_limit".equals(key)){
                if (StringUtil.isEmpty(value)){
                    buffer.append(warningMap.get(key)+" 不能为空");
                    return buffer.toString();
                }

                if (!StringUtil.validDoubleInterval(Double.parseDouble(value),0D,99999D)){
                    buffer.append(warningMap.get(key)+"（0~100000(不含100000)，正整数）");
                    return buffer.toString();
                }
            }
        }
        if (maxvo < minvo) {
            buffer.append("电压告警上限值:"+maxvo+"不符合要求，电压告警上限必须大于或等于电压告警下限");
            return buffer.toString();
        }
        if (maxcu < mincu) {
            buffer.append("电流告警上限值:"+maxcu+"不符合要求，电流告警上限必须大于或等于电流告警下限");
            return buffer.toString();
        }
        if (airSetTemperatureUpperLimit < airSetTemperatureLowerLimit){
            buffer.append("空调设置温度上限:"+airSetTemperatureUpperLimit+"不符合要求，空调设置温度上限必须大于或等于空调设置温度下限");
            return buffer.toString();
        }

        return null;
    }

    private HashMap<String, String> getInsertMap(Device2 device) {
        HashMap<String, String> map = new HashMap<>();
        String type = device.getType();
        if ("server".equals(type)) {
            map.put("host_name", device.getHostName());
            map.put("ip", device.getIp());
            map.put("logical_site", device.getLogicalSite());
            map.put("cpu_type", device.getCpuType());
            map.put("gpu_type", device.getGpuType());
            map.put("memory", device.getMemory());
            map.put("hard_disk", device.getHardDisk());
            map.put("maintenance_provider", device.getMaintenanceProvider());
            map.put("rated_power", device.getRatedPower());
            map.put("located_cabinet", device.getLocatedCabinet());

            map.put("ipv6", device.getIpv6());
            map.put("data_center", device.getDataCenter());
            map.put("po", device.getPo());
            map.put("network_card", device.getNetworkCard());
            map.put("manufacture_type", device.getManufactureType());
            map.put("oob_ip", device.getOobIp());
            map.put("device_model", device.getDeviceModel());
            map.put("oob_mac", device.getOobMac());
            /**补充缺少的字段*/
            map.put("hardware_version", device.getHardwareVersion());
            map.put("drive_release_time", device.getDriveReleaseTime());
            map.put("driver_version", device.getDriverVersion());
            map.put("manufacture_date", device.getManufactureDate());
            map.put("server_type",device.getServerType());
            //预测功耗上限
            map.put("forecast_power_upper_limit",device.getForecastPowerUpperLimit()+"");
            //比较dao层，缺少rated_freq，power_on_status，purchase_date
        } else if ("cabinet".equals(type)) {
            map.put("data_center", device.getDataCenter());
            map.put("height", device.getHeight());  //number
            map.put("cabinet_type", device.getCabinetType());
            map.put("rated_power", device.getRatedPower()); //number
            map.put("label", device.getLabel());
            map.put("init_position", device.getInitPosition());
            map.put("device_model", device.getDeviceModel());
            map.put("current_type", device.getCurrentType());
            map.put("logic_domain", device.getLogicDomain());
            map.put("rent_price", device.getRentPrice());
            map.put("device_model", device.getDeviceModel());
            map.put("power_supply_path", device.getPowerSupplyPath());
            map.put("dsw_name", device.getDswName());
            map.put("asw_name", device.getAswName());
            map.put("planned_server_number", device.getPlannedServerNumber());
            map.put("width", device.getWidth());
            map.put("manufacture_date", device.getManufactureDate());

            //比较dao层，缺少located_cabinet，ip,power_on_status，purchase_date
        } else if ("air".equals(type)) {
            map.put("name", device.getName());
            map.put("weight", device.getWeight());
            map.put("rated_voltage", device.getRatedVoltage());
            map.put("refrigerating_capacity", device.getRefrigeratingCapacity());
            map.put("heating_capacity", device.getHeatingCapacity());
            map.put("crygen", device.getCrygen());
            map.put("safety_valve_pressure", device.getSafetyValvePressure());
            map.put("overheating_temperature", device.getOverheatingTemperature());

            map.put("device_model", device.getDeviceModel());
            map.put("rated_power", device.getRatedPower());
            map.put("humidification_capacity", device.getHumidificationCapacity());
            map.put("humidifier_rated_power", device.getHumidifierRatedPower());
            map.put("compressor_rated_power", device.getCompressorRatedPower());
            map.put("heater_rated_power", device.getHeaterRatedPower());
            map.put("fan_rated_power", device.getFanRatedPower());
            map.put("turn_off_pressure", device.getTurnOffPressure());
            map.put("manufacture_date", device.getManufactureDate());
            //新增空调设置温度上限/下限
            map.put("air_set_temperature_upper_limit", device.getAirSetTemperatureUpperLimit()+"");
            map.put("air_set_temperature_lower_limit", device.getAirSetTemperatureLowerLimit()+"");
            //比较dao层，缺少located_cabinet，ip,data_center，purchase_date
        } else if ("pdu".equals(type)) {
            map.put("rated_power", device.getRatedPower());
            map.put("name", device.getName());
            map.put("located_cabinet", device.getLocatedCabinet());
            map.put("device_model", device.getDeviceModel());
            map.put("maximum_voltage_limit", device.getMaximumVoltageLimit());
            map.put("minimum_voltage_limit", device.getMinimumVoltageLimit());
            map.put("maximum_current_limit", device.getMaximumCurrentLimit());
            map.put("minimum_current_limit", device.getMinimumCurrentLimit());
            map.put("manufacture_date", device.getManufactureDate());

            //比较dao层，缺少rated_power，ip,data_center，purchase_date
        }else if("ipc".equals(type)){
            map.put("i_ip",device.getIp());
            map.put("i_port",String.valueOf(device.getIPort()));
            map.put("agreement",device.getAgreement());
            map.put("located_cabinet", device.getLocatedCabinet());
            map.put("ip", device.getIp());
            map.put("device_model", device.getDeviceModel());
            map.put("rated_power", device.getRatedPower()); //number
            map.put("serial_port", device.getSerialPort()); //串口
            map.put("baud_rate", device.getBaudRate()); //波特率
            map.put("parity_bit", device.getParityBit()); //奇偶校验位
            map.put("data_bit", device.getDataBit()); //数据位
            map.put("stop_bit", device.getStopBit()); //停止位
            map.put("weight", device.getWeight());
            map.put("addr",device.getAddr());
            map.put("purchase_date", device.getPurchaseDate());
        } else {
            if(StringUtil.isEmpty(type)){
                map.put("ErrMsg", "设备类型不能为空");
            } else {
                map.put("ErrMsg", "设备类型:"+type+"不存在 ");
            }
            return map;
        }
        map.put("device_id", device.getDeviceId());
        map.put("type", type);
        map.put("room", device.getRoom());
        map.put("location_id", device.getLocationId());
        map.put("remarks", device.getRemarks());
        map.put("business_type", device.getBusinessType());
        String createTime = DateUtil.millisecondToDate(System.currentTimeMillis());
        map.put("create_time", createTime);
        map.put("modified_time", createTime);
        map.put("usage_status", device.getUsageStatus());
        map.put("administrator", device.getAdministrator());
        /**补充缺少的字段*/
        map.put("manufacturer", device.getManufacturer());
        map.put("save_function", device.getSaveFunction());
        map.put("incompatible_feature", device.getIncompatibleFeature());

        if("ipc".equals(type)){
            map.remove("save_function");
            map.remove("business_type");
            map.remove("incompatible_feature");
            map.remove("manufacturer");
        }
        return map;
    }

    private HashMap<String, String> getUpdateMap(Device2 device) {
        HashMap<String, String> map = new HashMap<>();
        String type = device.getType();
        if ("server".equals(type)) {
            map.put("business_type", device.getBusinessType());
            map.put("ipv6", device.getIpv6());
            map.put("ip", device.getIp());
            map.put("data_center", device.getDataCenter());
            map.put("located_cabinet", device.getLocatedCabinet());
            map.put("administrator", device.getAdministrator());
            map.put("room", device.getRoom());
            map.put("logical_site", device.getLogicalSite());
            map.put("location_id", device.getLocationId());
            map.put("oob_ip", device.getOobIp());
            //map.put("strategy_id", String.valueOf(device.getStrategyID()));
            map.put("memory", device.getMemory());
            map.put("hard_disk", device.getHardDisk());
            /**补充缺少的字段*/
            map.put("hardware_version", device.getHardwareVersion());
            map.put("drive_release_time", device.getDriveReleaseTime());
            map.put("driver_version", device.getDriverVersion());
            //预测功耗上限
            map.put("forecast_power_upper_limit",device.getForecastPowerUpperLimit()+"");
        } else if ("cabinet".equals(type)) {
            map.put("room", device.getRoom());
            map.put("location_id", device.getLocationId());
            map.put("label", device.getLabel());
            map.put("current_type", device.getCurrentType());
            map.put("power_supply_path", String.valueOf(device.getPowerSupplyPath()));
            map.put("logic_domain", device.getLogicDomain());
            map.put("dsw_name", device.getDswName());
            map.put("asw_name", device.getAswName());
            map.put("rent_price", String.valueOf(device.getRentPrice()));
            map.put("planned_server_number", String.valueOf(device.getPlannedServerNumber()));
            map.put("administrator", device.getAdministrator());
            map.put("business_type", device.getBusinessType());
            map.put("data_center", device.getDataCenter());
        } else if ("air".equals(type)) {
            map.put("location_id", device.getLocationId());
            map.put("administrator", device.getAdministrator());
            map.put("room", device.getRoom());
            map.put("crygen", device.getCrygen());
            map.put("name", device.getName());
            //新增空调设置温度上限/下限
            map.put("air_set_temperature_upper_limit", device.getAirSetTemperatureUpperLimit()+"");
            map.put("air_set_temperature_lower_limit", device.getAirSetTemperatureLowerLimit()+"");
        } else if ("pdu".equals(type)) {
            map.put("location_id", device.getLocationId());
            map.put("administrator", device.getAdministrator());
            map.put("room", device.getRoom());
            map.put("located_cabinet", device.getLocatedCabinet());
            map.put("maximum_voltage_limit", String.valueOf(device.getMaximumVoltageLimit()));
            map.put("minimum_voltage_limit", String.valueOf(device.getMinimumVoltageLimit()));
            map.put("maximum_current_limit", String.valueOf(device.getMaximumCurrentLimit()));
            map.put("minimum_current_limit", String.valueOf(device.getMinimumCurrentLimit()));
            map.put("name", device.getName());
        }else if("ipc".equals(type)){
            map.put("i_port",String.valueOf(device.getIPort()));
            map.put("located_cabinet",device.getLocatedCabinet());
            map.put("room",device.getRoom());
            map.put("agreement",device.getAgreement());
            map.put("location_id",device.getLocationId());
            map.put("serial_port", device.getSerialPort()); //串口
            map.put("baud_rate", device.getBaudRate()); //波特率
            map.put("parity_bit", device.getParityBit()); //奇偶校验位
            map.put("data_bit", device.getDataBit()); //数据位
            map.put("stop_bit", device.getStopBit()); //停止位
        } else {
            map.put("ErrMsg", "设备类型:"+type+"不存在 ");
            return map;
        }
        map.put("device_id", device.getDeviceId());
        map.put("type", type);
        map.put("remarks", device.getRemarks());
        String modifiedTime = DateUtil.millisecondToDate(System.currentTimeMillis());
        map.put("modified_time", modifiedTime);
        map.put("usage_status", device.getUsageStatus());
        /**补充缺少的字段*/
        map.put("manufacturer", device.getManufacturer());
        map.put("manufacture_date", device.getManufactureDate());

        return map;
    }

    /**
     * 将设备详情的map结合转换位Device2格式返回客户端
     *
     * @param map NOTNULL
     */
    private Device2 mapToDevice2(Map<String, String> map) {
        Device2.Builder builder = Device2.newBuilder();
        String type = map.get("type");
        if ("server".equals(type)) {
            String serverType = deviceServerDao.selectServerType(map.get("device_id"));
            if("arm".equals(serverType)){
                builder.setServerType("arm");
            }else{
                builder.setServerType("x86");
            }
            builder.setIp(getNotNull(map.get("ip")));
            builder.setHardDisk(getNotNull(map.get("hard_disk")));
            builder.setMemory(getNotNull(map.get("memory")));
            builder.setHostName(getNotNull(map.get("host_name")));
            builder.setIpv6(getNotNull(map.get("ipv6")));
            builder.setCpuType(getNotNull(map.get("cpu_type")));
            builder.setGpuType(getNotNull(map.get("gpu_type")));
            builder.setNetworkCard(getNotNull(map.get("network_card")));
            builder.setManufactureType(getNotNull(map.get("manufacture_type")));
            builder.setLogicalSite(getNotNull(map.get("logical_site")));
            builder.setOobIp(getNotNull(map.get("oob_ip")));
            builder.setOobMac(getNotNull(map.get("oob_mac")));
            builder.setMaintenanceProvider(getNotNull(map.get("maintenance_provider")));
            builder.setPo(getNotNull(map.get("po")));
            builder.setLocatedCabinet(getNotNull(map.get("located_cabinet")));
            builder.setDataCenter(getNotNull(map.get("data_center")));
            builder.setHardwareVersion(getNotNull(map.get("hardware_version")));
            builder.setDriverVersion(getNotNull(map.get("driver_version")));
            builder.setDriveReleaseTime(getNotNull(map.get("drive_release_time")));
            builder.setRatedPower(map.get("rated_power"));
            if(map.get("forecast_power_upper_limit")!=null){
                builder.setForecastPowerUpperLimit(Double.valueOf(map.get("forecast_power_upper_limit")));
            }
        } else if ("cabinet".equals(type)) {
            builder.setDataCenter(getNotNull(map.get("data_center")));
            builder.setCurrentType(getNotNull(map.get("current_type")));
            builder.setPowerSupplyPath(map.get("power_supply_path"));
            builder.setLogicDomain(getNotNull(map.get("logic_domain")));
            builder.setDswName(getNotNull(map.get("dsw_name")));
            builder.setAswName(getNotNull(map.get("asw_name")));
            builder.setRentPrice(map.get("rent_price"));
            builder.setPlannedServerNumber(map.get("planned_server_number"));
            builder.setCabinetType(getNotNull(map.get("cabinet_type")));
            builder.setHeight(map.get("height"));
            builder.setWidth(map.get("width"));
            builder.setInitPosition(getNotNull(map.get("init_position")));
            builder.setLabel(getNotNull(map.get("label")));
            builder.setRatedPower(map.get("rated_power"));
        } else if ("air".equals(type)) {
            builder.setName(getNotNull(map.get("name")));
            builder.setRefrigeratingCapacity(map.get("refrigerating_capacity"));
            builder.setRatedVoltage(map.get("rated_voltage"));
            builder.setHeatingCapacity(map.get("heating_capacity"));
            builder.setHumidificationCapacity(map.get("humidification_capacity"));
            builder.setCrygen(getNotNull(map.get("crygen")));
            builder.setWeight(map.get("weight"));
            builder.setCompressorRatedPower(map.get("compressor_rated_power"));
            builder.setHeaterRatedPower(map.get("heater_rated_power"));
            builder.setFanRatedPower(map.get("fan_rated_power"));
            builder.setHumidifierRatedPower(map.get("humidifier_rated_power"));
            builder.setSafetyValvePressure(map.get("safety_valve_pressure"));
            builder.setOverheatingTemperature(map.get("overheating_temperature"));
            builder.setTurnOffPressure(map.get("turn_off_pressure"));
            builder.setRatedPower(map.get("rated_power"));

            if(map.get("air_set_temperature_upper_limit")!=null){
                builder.setAirSetTemperatureUpperLimit((Double.valueOf(map.get("air_set_temperature_upper_limit"))));
            }
            if(map.get("air_set_temperature_lower_limit")!=null){
                builder.setAirSetTemperatureLowerLimit((Double.valueOf(map.get("air_set_temperature_lower_limit"))));
            }
        } else if ("pdu".equals(type)) {
            builder.setName(getNotNull(map.get("name")));
            builder.setLocatedCabinet(getNotNull(map.get("located_cabinet")));
            builder.setManufacturer(getNotNull(map.get("manufacturer")));
            builder.setMaximumVoltageLimit(map.get("maximum_voltage_limit"));
            builder.setMinimumVoltageLimit(map.get("minimum_voltage_limit"));
            builder.setMaximumCurrentLimit(map.get("maximum_current_limit"));
            builder.setMinimumCurrentLimit(map.get("minimum_current_limit"));
            builder.setRatedPower(map.get("rated_power"));
        } else if("ipc".equals(type)){
            builder.setAddr(getNotNull(map.get("addr")));//所在位置
            builder.setPurchaseDate(getNotNull(map.get("purchase_date")));//购买时间
            builder.setRatedPower(getNotNull(map.get("rated_power"))); //额定功率
            builder.setIp(getNotNull(map.get("ip")));
            if(map.get("i_port")==null){
                builder.setIPort(0);
            }else{
                builder.setIPort(Integer.valueOf(map.get("i_port")));
            }
            builder.setLocatedCabinet(getNotNull(map.get("located_cabinet")));
            builder.setAgreement(getNotNull(map.get("agreement")));
            builder.setSerialPort(getNotNull(map.get("serial_port")));
            builder.setBaudRate(getNotNull(map.get("baud_rate")));//波特率
            builder.setParityBit(getNotNull(map.get("parity_bit")));//奇偶校验位
            builder.setDataBit(getNotNull(map.get("data_bit")));//数据位
            builder.setStopBit(getNotNull(map.get("stop_bit"))); //停止位
            builder.setWeight(getNotNull(map.get("weight"))); //停止位
        }
        builder.setDeviceId(getNotNull(map.get("device_id")));
        builder.setType(getNotNull(map.get("type")));
        builder.setBusinessType(getNotNull(map.get("business_type")));
        builder.setRoom(getNotNull(map.get("room")));
        builder.setLocationId(getNotNull(map.get("location_id")));
        builder.setDeviceModel(getNotNull(map.get("device_model")));
        builder.setAdministrator(getNotNull(map.get("administrator")));
        builder.setCreateTime(getNotNull(map.get("create_time")));
        builder.setModifiedTime(getNotNull(map.get("modified_time")));
        builder.setUsageStatus(getNotNull(map.get("usage_status")));
        builder.setRemarks(getNotNull(map.get("remarks")));
        /**补充缺少的字段*/
        builder.setManufacturer(getNotNull(map.get("manufacturer")));
        builder.setManufactureDate(getNotNull(map.get("manufacture_date")));
        builder.setIncompatibleFeature(getNotNull(map.get("incompatible_feature")));
        builder.setSaveFunction(getNotNull(map.get("save_function")));
        return builder.build();
    }

    private Map<String, String> mapToDetailMap(Map<String, String> map) {
        if (map == null) {
            return null;
        }
        Map<String, String> newMap = new HashMap<>();
        String type = map.get("type");
        if ("server".equals(type)) {
            //获取服务类型
            String serverType = deviceServerDao.selectServerType(map.get("device_id"));
            if("arm".equals(serverType)){
                newMap.put("server_type", "arm");
            }else{
                newMap.put("server_type", "x86");
            }
            newMap.put("ip", getNotNull(map.get("ip")));
            newMap.put("hard_disk", getNotNull(map.get("hard_disk")));
            newMap.put("memory", getNotNull(map.get("memory")));
            newMap.put("host_name", getNotNull(map.get("host_name")));
            newMap.put("ipv6", getNotNull(map.get("ipv6")));
            newMap.put("cpu_type", getNotNull(map.get("cpu_type")));
            newMap.put("gpu_type", getNotNull(map.get("gpu_type")));
            newMap.put("network_card", getNotNull(map.get("network_card")));
            newMap.put("manufacture_type", getNotNull(map.get("manufacture_type")));
            newMap.put("logical_site", getNotNull(map.get("logical_site")));
            newMap.put("oob_ip", getNotNull(map.get("oob_ip")));
            newMap.put("oob_mac", getNotNull(map.get("oob_mac")));
            newMap.put("maintenance_provider", getNotNull(map.get("maintenance_provider")));
            newMap.put("po", getNotNull(map.get("po")));
            newMap.put("located_cabinet", getNotNull(map.get("located_cabinet")));
            newMap.put("data_center", getNotNull(map.get("data_center")));
            newMap.put("hardware_version", getNotNull(map.get("hardware_version")));
            newMap.put("driver_version", getNotNull(map.get("driver_version")));
            newMap.put("drive_release_time", getNotNull(map.get("drive_release_time")));
            if(StringUtils.isNotBlank(getNotNull(map.get("forecast_power_upper_limit")))){
                BigDecimal forecastPowerUpperLimit=new BigDecimal(map.get("forecast_power_upper_limit")).setScale(0, BigDecimal.ROUND_HALF_UP);
                newMap.put("forecast_power_upper_limit",  forecastPowerUpperLimit.toString());
            }else{
                newMap.put("forecast_power_upper_limit", getNotNull(map.get("forecast_power_upper_limit")));
            }


        } else if ("cabinet".equals(type)) {
            newMap.put("data_center", getNotNull(map.get("data_center")));
            newMap.put("current_type", getNotNull(map.get("current_type")));
            newMap.put("power_supply_path", getNotNull(map.get("power_supply_path")));
            newMap.put("logic_domain", getNotNull(map.get("logic_domain")));
            newMap.put("dsw_name", getNotNull(map.get("dsw_name")));
            newMap.put("asw_name", getNotNull(map.get("asw_name")));
            newMap.put("rent_price", getNotNull(map.get("rent_price")));
            newMap.put("planned_server_number", getNotNull(map.get("planned_server_number")));
            //newMap.put("device_total_rated_power", getNotNull(map.get("device_total_rated_power")));
            newMap.put("cabinet_type", getNotNull(map.get("cabinet_type")));
            newMap.put("height", getNotNull(map.get("height")));
            newMap.put("width", getNotNull(map.get("width")));
            newMap.put("init_position", getNotNull(map.get("init_position")));
            newMap.put("label", getNotNull(map.get("label")));
        } else if ("air".equals(type)) {
            newMap.put("name", getNotNull(map.get("name")));
            newMap.put("refrigerating_capacity", getNotNull(map.get("refrigerating_capacity")));
            newMap.put("rated_voltage", getNotNull(map.get("rated_voltage")));
            newMap.put("heating_capacity", getNotNull(map.get("heating_capacity")));
            newMap.put("humidification_capacity", getNotNull(map.get("humidification_capacity")));
            newMap.put("crygen", getNotNull(map.get("crygen")));
            newMap.put("weight", getNotNull(map.get("weight")));
            newMap.put("compressor_rated_power", getNotNull(map.get("compressor_rated_power")));
            newMap.put("heater_rated_power", getNotNull(map.get("heater_rated_power")));
            newMap.put("fan_rated_power", getNotNull(map.get("fan_rated_power")));
            newMap.put("humidifier_rated_power", getNotNull(map.get("humidifier_rated_power")));
            newMap.put("safety_valve_pressure", getNotNull(map.get("safety_valve_pressure")));
            newMap.put("overheating_temperature", getNotNull(map.get("overheating_temperature")));
            newMap.put("turn_off_pressure", getNotNull(map.get("turn_off_pressure")));
            newMap.put("air_set_temperature_upper_limit", getNotNull(map.get("air_set_temperature_upper_limit")));
            newMap.put("air_set_temperature_lower_limit", getNotNull(map.get("air_set_temperature_lower_limit")));
        } else if ("pdu".equals(type)) {
            newMap.put("name", getNotNull(map.get("name")));
            newMap.put("located_cabinet", getNotNull(map.get("located_cabinet")));
            newMap.put("manufacturer", getNotNull(map.get("manufacturer")));
            newMap.put("maximum_voltage_limit", getNotNull(map.get("maximum_voltage_limit")));
            newMap.put("minimum_voltage_limit", getNotNull(map.get("minimum_voltage_limit")));
            newMap.put("maximum_current_limit", getNotNull(map.get("maximum_current_limit")));
            newMap.put("minimum_current_limit", getNotNull(map.get("minimum_current_limit")));
        }else if("ipc".equals(type)){
            newMap.put("i_port",String.valueOf(map.get("i_port")));
            newMap.put("located_cabinet",map.get("located_cabinet"));
            newMap.put("room",map.get("room"));
            newMap.put("agreement",map.get("agreement"));
            newMap.put("location_id",map.get("location_id"));
            newMap.put("administrator",map.get("administrator"));
            newMap.put("ip", map.get("ip"));
            newMap.put("serial_port", map.get("serial_port")); //串口
            newMap.put("baud_rate", map.get("baud_rate")); //波特率
            newMap.put("parity_bit", map.get("parity_bit")); //奇偶校验位
            newMap.put("data_bit", map.get("data_bit")); //数据位
            newMap.put("stop_bit", map.get("stop_bit")); //停止位
            newMap.put("weight", map.get("weight"));
            newMap.put("addr",map.get("addr"));
        } else {
            logger.error("devicetype is available");
            return null;
        }
        newMap.put("device_id", getNotNull(map.get("device_id")));
        newMap.put("type", getNotNull(map.get("type")));
        newMap.put("business_type", getNotNull(map.get("business_type")));
        newMap.put("room", getNotNull(map.get("room")));
        newMap.put("location_id", getNotNull(map.get("location_id")));
        newMap.put("device_model", getNotNull(map.get("device_model")));
        newMap.put("administrator", getNotNull(map.get("administrator")));
        newMap.put("create_time", getNotNull(map.get("create_time")));
        newMap.put("modified_time", getNotNull(map.get("modified_time")));
        newMap.put("usage_status", getNotNull(map.get("usage_status")));
        newMap.put("remarks", getNotNull(map.get("remarks")));
        /**补充缺少的字段*/
        newMap.put("manufacturer", getNotNull(map.get("manufacturer")));
        newMap.put("manufacture_date", getNotNull(map.get("manufacture_date")));
        newMap.put("purchase_date", getNotNull(map.get("purchase_date")));
        newMap.put("incompatible_feature", getNotNull(map.get("incompatible_feature")));
        newMap.put("save_function", getNotNull(map.get("save_function")));
        newMap.put("rated_power", getNotNull(map.get("rated_power")));
        return newMap;
    }

    /*
    校验参数合法性，包括字符长度，非法字符等
     */
    private String validate(String name, String value, int size) {
        return validate(name, value, 1, size);
    }

    private String validate(String name, String value, int min, int max) {
        StringBuffer buffer = new StringBuffer();
        if (!StringUtil.isLength(value,min,max)) {
            buffer.append(warningMap.get(name)+":"+value+"格式错误，长度超过限制");
            return buffer.toString();
        }
        return null;
    }

    public Map<String, String> getTypeMap(){
        Map<String, String> map = new HashMap<>();
        map.put("server","服务器");
        map.put("cabinet","机柜");
        map.put("air","空调");
        map.put("pdu","PDU");
        map.put("ipc","工控机");
        return map;
    }

    public Map<String, String> getWarningMap(){
        Map<String, String> map = new HashMap<>();
        map.put("device_id", "设备编号");
        map.put("type", "设备类型");
        map.put("room", "所属房间");
        map.put("location_id", "位置号");
        map.put("remarks", "备注");
        map.put("business_type", "大业务类");
        map.put("usage_status", "使用状态");
        map.put("administrator", "负责人");
        map.put("manufacturer", "生产商");
        map.put("manufacture_date", "生产年份");
        map.put("save_function", "保存功能");
        map.put("incompatible_feature", "不兼容功能");
        map.put("host_name", "主机名");
        map.put("ip", "设备IP");
        map.put("logical_site", "逻辑站点");
        map.put("cpu_type", "CPU型号");
        map.put("gpu_type", "GPU型号");
        map.put("memory", "内存");
        map.put("hard_disk", "硬盘");
        map.put("maintenance_provider", "维保厂商");
        map.put("rated_power", "额定功率");
        map.put("located_cabinet", "所在机柜");
        map.put("ipv6", "IPV6");
        map.put("data_center", "所属数据中心");
        map.put("po", "PO订单号");
        map.put("network_card", "网卡");
        map.put("manufacture_type", "厂商标准机型");
        map.put("oob_ip", "带外IP");
        map.put("device_model", "设备型号");
        map.put("oob_mac", "带外MAC");
        map.put("hardware_version", "驱动支持最低硬件版本");
        map.put("drive_release_time", "驱动发布时间");
        map.put("driver_version", "驱动版本");
        map.put("height", "高度");
        map.put("cabinet_type", "机柜类型");
        map.put("label", "标签");
        map.put("init_position", "机柜起始位置");
        map.put("current_type", "电流类型");
        map.put("logic_domain", "逻辑域");
        map.put("rent_price", "机房月费");
        map.put("power_supply_path", "电源路数");
        map.put("dsw_name", "DSW名称");
        map.put("asw_name", "ASW名称");
        map.put("planned_server_number", "规划服务器数量");
        map.put("width", "宽度");
        map.put("name", "名称");
        map.put("weight", "重量");
        map.put("rated_voltage", "额定电压");
        map.put("refrigerating_capacity", "额定制冷量");
        map.put("heating_capacity", "加热量");
        map.put("crygen", "制冷剂");
        map.put("safety_valve_pressure", "安全阀临界压力");
        map.put("overheating_temperature", "过热保护温度");
        map.put("humidification_capacity", "加湿量");
        map.put("humidifier_rated_power", "加湿额定功率");
        map.put("compressor_rated_power", "压缩机额定功率");
        map.put("heater_rated_power", "电加热额定功率");
        map.put("fan_rated_power", "风扇额定功率");
        map.put("turn_off_pressure", "高压关断压力");
        map.put("maximum_voltage_limit", "电压告警上限");
        map.put("minimum_voltage_limit", "电压告警下限");
        map.put("maximum_current_limit", "电流告警上限");
        map.put("minimum_current_limit", "电流告警下限");
        map.put("addr","位置");
        map.put("serial_port","串口");
        map.put("parity_bit","奇偶校验位");
        map.put("air_set_temperature_upper_limit","空调设置温度上限");
        map.put("air_set_temperature_lower_limit","空调设置温度下限");
        map.put("forecast_power_upper_limit","预测功耗上限");
        map.put("i_ip","IP");

        return map;
    }

    /**
     * 预测功耗上限告警
     * @param serverSN
     * @param power
     */
    private void warmPower(String serverSN,double power){
        try {
            VerifyEdgePO verifyEdgePO = new VerifyEdgePO();
            verifyEdgePO.setValue(String.valueOf(power));
            verifyEdgePO.setDeviceId(serverSN);
            verifyEdgePO.setType(2);
            warningService.verifyEdge(verifyEdgePO);
        }catch (Exception e){
         logger.error(e.getMessage());
        }
    }
    private Map<String,String> ipcMap(){
        Map<String, String> map = new HashMap<>();
        map.put("baud_rate","波特率");
        map.put("data_bit","数据位");
        map.put("stop_bit","停止位");
        map.put("i_port","端口");
        return map;
    }

    
}
